package com.fingard.dsp.bank.directbank.citic02;

import com.fingard.FGBiz;
import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directConfig.FtpSet;
import com.fingard.dsp.bank.directbank.FailCode;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.bankInterface.IBatPayRec;
import com.fingard.dsp.bank.directbank.citic02.util.FilePushUtil;
import com.fingard.dsp.bank.helpers.FileType;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.detail.RetAtsBatPayRecDetail;
import com.fingard.dsp.bank.reqrespobj.single.ReqQrySingle;
import com.fingard.dsp.bank.reqrespobj.single.ReqSingle;
import com.fingard.dsp.bank.reqrespobj.single.RetAtsSingle;
import com.fingard.dsp.bank.syncfile.FileItem;
import com.fingard.io.FileHelper;
import com.fingard.net.ConnState;
import com.fingard.net.FtpReceiver;
import com.fingard.net.MixFtp;
import com.fingard.net.SftpPortClient;
import com.fingard.text.StringHelper;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

import java.io.BufferedReader;
import java.io.File;
import java.io.StringReader;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;

public class CITIC02BatPayRec extends CITIC02Base implements IBatPayRec {
    @Override
    public RetAtsBatPayRec d_1988_BatPay(ReqBatPayRec p_req1988) throws Exception {
        return null;
    }

    @Override
    public RetAtsQryBatPayRec d_1998_QryBatPay(ReqQryBatPayRec p_req1998) throws Exception {
        return null;
    }

    @Override
    public RetAtsBatPayRec d_9188_BatPay(ReqBatPayRec p_req9188) throws Exception {
        RetAtsBatPayRec retAts = new RetAtsBatPayRec(p_req9188.reqHeader);
        retAts.reqSeqID = p_req9188.reqBatchNO;

        try {
            if("918801CNVRT".equals(p_req9188.reqHeader.commandCode)) {
                if(p_req9188.getTotalNum() == 1){
                    ReqSingle req9108 = new ReqSingle(p_req9188);//批量转单笔
                    CITIC02RealTime tmpRealTime = new CITIC02RealTime();
                    tmpRealTime.setSbLog(this.sbLog);
                    tmpRealTime.setLogFlushTime(this.logFlushTime);
                    tmpRealTime.reqHeader = req9108.reqHeader;
                    tmpRealTime.bankFront = this.bankFront;
                    req9108.singleDetail.askNumber = p_req9188.reqBatchNO;//批次号作为单笔流水号
                    RetAtsSingle retAts9108 = tmpRealTime.d_9108_RealTimeRec(req9108);
                    retAts9108.fillToBatRetAts(retAts);
                }else{
                    retAts.fillBatchFailed(p_req9188, FailCode.E9981, "总笔数需为1");
                }
            }else{
                /*
                 * 批量委托代扣提交 交互流程说明：1、通过FTP上传批量代扣文件;2、上传文件成功后发送XML报文通知银行处理;
                 */
                ActSetItem actItem = getBankConfig().getActSetItem(p_req9188.ownAct, "");
                if (actItem == null) {
                    retAts.respCode = "0";
                    retAts.respInfo = "未找到账号[" + p_req9188.ownAct + "]商户配置信息";
                    retAts.reqSeqID = p_req9188.reqBatchNO;
                    retAts.transState = PaymentState.FAIL_Batch;
                    retAts.payInfoCode = FailCode.E9981;
                    retAts.writeRetToATS();
                    return retAts;
                }
                // 批次请求文件内容
                StringBuilder sbFileContent = new StringBuilder();

                // 批次流水映射文件内容
                StringBuilder seqNoMappingContent = new StringBuilder();

                int seqNo = 0;
                // 报文长度（8）+地区码（4）+业务种类（6）+委托单位（15）+业务单位（15）+渠道号（8）+外部交易码（15）
                String area = getBankConfig().getValueAsString("area");
                String businessTypes = getBankConfig().getValueAsString("businessTypes");
                String entrustmentUnit = getBankConfig().getValueAsString("entrustmentUnit");
                String businessUnit = getBankConfig().getValueAsString("businessUnit");
                String channelNumber = getBankConfig().getValueAsString("channelNumber");
                String tmpFifteen = "%-15s";
                StringBuilder sbContent = new StringBuilder();
                sbContent.append(String.format("%-4s", area));// 地区码
                sbContent.append(String.format("%-6s", businessTypes));// 业务种类
                sbContent.append(String.format(tmpFifteen, entrustmentUnit));// 委托单位
                sbContent.append(String.format(tmpFifteen, businessUnit));// 业务单位
                sbContent.append(String.format("%-8s", channelNumber));// 渠道号
                sbContent.append(String.format(tmpFifteen, "ZLDS002"));// 外部交易码
                while (p_req9188.readRecord()) {
                    if (seqNoMappingContent.length() > 0) {
                        seqNoMappingContent.append("\r\n");
                    }
                    if (sbFileContent.length() > 0) {
                        sbFileContent.append("\r\n");
                    }
                    seqNo++;
                    String seqNoId = String.format("%06d", seqNo);
                    String payName = p_req9188.readedDetail.payName;
                    String payAct = p_req9188.readedDetail.payAct;
                    String phone = p_req9188.readedDetail.cellPhone;
                    String cardFlag = "";
                    String sameBnk = "";
                    if ("1".equals(p_req9188.readedDetail.sameBnk)) {
                        sameBnk = "1";
                    } else {
                        sameBnk = "2";
                    }
                    String isPrivate = "";
                    if ("1".equals(p_req9188.readedDetail.isPrivate)) {
                        isPrivate = "1";
                    } else {
                        isPrivate = "2";
                    }
                    cardFlag = sameBnk + isPrivate;
                    String certType = convertCertTypeToBank(p_req9188.readedDetail.certType);
                    String certNum = p_req9188.readedDetail.certNum;
                    String authCode = p_req9188.readedDetail.sourceNoteCode;
                    String payAmount = p_req9188.readedDetail.payAmount;
                    String signNo = p_req9188.readedDetail.authCode;
                    sbFileContent.append(MessageFormat.format("{0}|{1}|{2}|{3}|{4}|{5}|{6}|{7}|{8}|{9}", seqNoId, payName, payAct, phone, cardFlag, certType, certNum, payAmount, authCode, signNo));
                    seqNoMappingContent.append(p_req9188.readedDetail.askNumber).append(",").append(seqNoId);
                }

                String tmpUploadFileContent = sbFileContent.toString();
                WriteBankLogLn2("批次请求文件内容:\r\n" + tmpUploadFileContent);

                // 读取批次文件序号
                String tmpMarkDataDir = getTempFileDirectory();
                int maxBatch = 0;
                File dataFileDir = new File(tmpMarkDataDir);
                if (dataFileDir.exists()) {
                    int len = dataFileDir.listFiles().length;
                    if (len > 0) {
                        maxBatch = len + 1;
                    } else {
                        maxBatch = 1;
                    }
                } else {
                    maxBatch = 1;
                }
                String tmpBatchSeqNo = String.format("%4s", maxBatch).replace(" ", "0");

                // 流水映射文件写入本地
                String tmpLocalSeqFilePath = StringHelper.trimEnd(tmpMarkDataDir, File.separator) + File.separator + p_req9188.reqBatchNO + "_" + tmpBatchSeqNo + ".txt";
                WriteBankLogLn2("批次映射文件路径: " + tmpLocalSeqFilePath);
                FileHelper.writeFile(tmpLocalSeqFilePath, seqNoMappingContent.toString(), getCharset());
                FileItem fileItem = new FileItem();
                fileItem.localFilePath = tmpLocalSeqFilePath;
                fileItem.relativePath = this.getRelativeDataDirPath(tmpLocalSeqFilePath);
                fileItem.fileType = FileType.dataFile;
                String syncRet = FGBiz.clusterCenter.syncFile(fileItem);
                if (StringHelper.hasAnyChar(syncRet)) {
                    WriteBankLogLn2(syncRet);
                }

                boolean filePush = getBankConfig().getValueAsBool("filePush");
                if (filePush) {
                    FilePushUtil filePushUtil = new FilePushUtil();
                    filePushUtil.bankFront = this.bankFront;
                    filePushUtil.reqHeader = this.reqHeader;
                    filePushUtil.sbLog = this.sbLog;
                    filePushUtil.filePush(tmpLocalSeqFilePath);
                }

                // 批次文件内容写入本地
                String merchatId = actItem.merchantId;
                String tmpUploadFileName = "F" + bankFront.org + "_S5IP_001_ZLDS_" + Format.Date8Format.format(p_req9188.getPayDateTime()) + merchatId + tmpBatchSeqNo + ".REQ";
                String tmpLocalMarkPath = StringHelper.trimEnd(tmpMarkDataDir, File.separator) + File.separator + tmpUploadFileName;
                WriteBankLogLn2("批次文件内容保存本地路径: " + tmpLocalMarkPath);
                FileHelper.writeFile(tmpLocalMarkPath, tmpUploadFileContent, getCharset());

                fileItem.localFilePath = tmpLocalMarkPath;
                fileItem.relativePath = this.getRelativeDataDirPath(tmpLocalMarkPath);
                fileItem.fileType = FileType.dataFile;
                syncRet = FGBiz.clusterCenter.syncFile(fileItem);
                if (StringHelper.hasAnyChar(syncRet)) {
                    WriteBankLogLn2(syncRet);
                }

                FtpSet ftpSet = bankFront.getFtpSet("bat");
                this.WriteBankLogLn("第一台FTP/SFTP上传地址" + ftpSet.serverIP + ":" + ftpSet.port);
                String sftpFilePath = StringHelper.trimEnd(ftpSet.upDir, "/") + "/" + tmpUploadFileName;
                WriteBankLogLn2("第一台FTP/SFTP服务器文件上传路径:" + sftpFilePath);
                MixFtp mixFtp = new MixFtp(ftpSet);
                FtpReceiver ftpReceiver = mixFtp.uploadFileToDir(tmpLocalMarkPath,ftpSet.upDir, tmpUploadFileName);
                boolean isCompleted = ftpReceiver.isCompleted;
                if(isCompleted){
                	WriteBankLogLn2("第一台上传成功");
                }else{
                	WriteBankLogLn2("第一台上传出现问题："+ftpReceiver.connMsg);
                }
                if (isCompleted && getBankConfig().getValueAsBool("uploadFTPSwifch")) {
                    FtpSet ftpSet2 = bankFront.getFtpSet("bat2");
                    this.WriteBankLogLn("第二台FTP/SFTP上传地址" + ftpSet2.serverIP + ":" + ftpSet2.port);
                    String sftpFilePath2 = StringHelper.trimEnd(ftpSet2.upDir, "/") + "/" + tmpUploadFileName;
                    WriteBankLogLn2("第二台FTP/SFTP服务器文件上传路径:" + sftpFilePath2);
                    MixFtp mixFtp2 = new MixFtp(ftpSet2);
                    FtpReceiver ftpReceiver2 = mixFtp2.uploadFileToDir(tmpLocalMarkPath,ftpSet.upDir, tmpUploadFileName);
                    isCompleted = ftpReceiver.isCompleted;
                    if (!ftpReceiver2.isCompleted) {
                        isCompleted = false;
                        WriteBankLogLn2("第二台上传出现问题："+ftpReceiver2.connMsg);
                    }else{
                    	WriteBankLogLn2("第二台上传成功");
                    }
                }
                if (isCompleted) {
                    // 发送报文
                    XmlTextWriter xmlWriter = new XmlTextWriter();
                    xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"" + getCharset() + "\"?>");
                    xmlWriter.writeStartElement("ROOT");
                    xmlWriter.writeElementString("trancode", "ZLDS002"); // 交易代码
                    xmlWriter.writeElementString("sndseqno", p_req9188.reqBatchNO);
                    xmlWriter.writeElementString("mrchname", actItem.userCode);
                    xmlWriter.writeElementString("mrchtype", "0401");// 0401
                    // 金融服务类-保险费
                    xmlWriter.writeElementString("mccprtcno", actItem.appId);
                    xmlWriter.writeElementString("totamt", p_req9188.totalAmt);
                    xmlWriter.writeElementString("totnum", p_req9188.totalNum);
                    xmlWriter.writeElementString("filename", tmpUploadFileName);
                    xmlWriter.writeEndDocument();
                    String tmpStrPlain = xmlWriter.toXmlString();
                    String result = sbContent.toString();
                    String sendMessage = result + tmpStrPlain;
                    WriteBankLogLn2("发送银行请求数据明文:\r\n" + sendMessage);
                    String[] tmpRetStr = sendToBank(sendMessage);
                    if (tmpRetStr[0].length() == 0) {
                        WriteBankLogStep3(tmpRetStr[1]);
                        WriteBankLogLn2("银行响应数据明文:\r\n" + tmpRetStr[1]);
                        StringBuilder tmpSbMsg = new StringBuilder();
                        XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpRetStr[1], tmpSbMsg);
                        if (tmpBkReader != null) {
                            String tmpRespCode = tmpBkReader.getFirstText("/ROOT/respcode");
                            if (tmpRespCode == null) {
                                retAts.respInfo = "通讯失败";
                                retAts.transState = "BatchFailed";
                                retAts.payInfoCode = "E9999";
                            } else {
                                retAts.respCode = "0";
                                retAts.respInfo = tmpBkReader.getFirstText("/ROOT/respinfo");
                                retAts.transState = tmpRespCode;
                                retAts.payInfoCode = tmpRespCode;
                            }
                        } else {
                            retAts.respCode = "-1";
                            retAts.respInfo = tmpSbMsg.toString();
                        }
                    } else {
                        retAts.respCode = "-1";
                        retAts.respInfo = tmpRetStr[1];
                    }
                } else if (ConnState.FAIL.equals(ftpReceiver.connState)) {
                    retAts.respInfo = "上传通讯失败";
                    retAts.transState = "BatchFailed";
                    retAts.payInfoCode = "E9999";
                } else {
                    retAts.respCode = "-1";
                    retAts.respInfo = ftpReceiver.connMsg;
                }
            }
        } catch (Exception ex) {
            //ex.printStackTrace();
            retAts.respCode = "-1";
            retAts.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        retAts.writeRetToATS();
        return retAts;
    }

    @Override
    public RetAtsQryBatPayRec d_9198_QryBatPay(ReqQryBatPayRec p_req9198) throws Exception {
        RetAtsQryBatPayRec retAts = new RetAtsQryBatPayRec(p_req9198.reqHeader);
        retAts.reqSeqID = p_req9198.reqBatchNO;

        try {
            if("918801CNVRT".equals(p_req9198.reqHeader.commandCode)){
                ReqQrySingle req9144 = new ReqQrySingle(p_req9198);//批量转单笔
                CITIC02RealTime tmpRealTime = new CITIC02RealTime();
                tmpRealTime.setSbLog(this.sbLog);
                tmpRealTime.setLogFlushTime(this.logFlushTime);
                tmpRealTime.reqHeader = req9144.reqHeader;
                tmpRealTime.bankFront = this.bankFront;
                RetAtsSingle ret9144 = tmpRealTime.d_9144_QryRealTimeRec(req9144);
                ret9144.fillToBatRetAts(retAts);
            }else{
                /*
                 * 批量委托代扣状态查询 交互流程说明：1、从FTP下载目录下载指定文件解析处理
                 */
                ActSetItem actItem = getBankConfig().getActSetItem(p_req9198.ownAct, "");
                if (actItem == null) {
                    retAts.respCode = "0";
                    retAts.respInfo = "未找到账号[" + p_req9198.ownAct + "]商户配置信息";
                    retAts.writeAfterDetail();
                    return retAts;
                }
                File tmpSeqNoMappingDir = new File(getTempFileDirectory(p_req9198.getBgnDateTime()));
                if (tmpSeqNoMappingDir.exists()) {
                    File[] tmpSeqMappingFileList = tmpSeqNoMappingDir.listFiles();
                    boolean isContinue = false;
                    String tmpSeqMappingFileName = "";
                    for (File tmpSeqMappingFile : tmpSeqMappingFileList) {
                        if (tmpSeqMappingFile.getName().contains(p_req9198.reqBatchNO)) {
                            isContinue = true;
                            tmpSeqMappingFileName = tmpSeqMappingFile.getName();
                            break;
                        }
                    }
                    if (isContinue) {
                        String[] tmpBatSeqMappingArray = tmpSeqMappingFileName.substring(0, tmpSeqMappingFileName.lastIndexOf('.')).split("_");
                        String tmpBatchNoId = tmpBatSeqMappingArray[1];
                        String tmpSeqNoContent = FileHelper.readFileText(getTempFileDirectory(p_req9198.getBgnDateTime()) + File.separator + tmpSeqMappingFileName, getCharset());
                        String[] tmpSeqNoArray = tmpSeqNoContent.split("\r\n");
                        Map<String, String> existSeqList = new HashMap<String, String>();
                        for (String tmpSeqNo : tmpSeqNoArray) {
                            if (StringHelper.hasAnyChar(tmpSeqNo)) {
                                String[] tempStr = tmpSeqNo.split(",");
                                existSeqList.put(tempStr[1], tempStr[0]);
                            }
                        }
                        String merchatId = actItem.merchantId;
                        String shortInstituteNo = getBankConfig().getValueAsString("shortInstituteNo");
                        String tmpDownloadFileName = "S5IP_T" + shortInstituteNo + "_001_ZLDS_" + Format.Date8Format.format(p_req9198.getBgnDateTime()) + merchatId + tmpBatchNoId + ".ANS";
                        WriteBankLogLn("FTP文件名:\r\n" + tmpDownloadFileName);
                        FtpSet ftpSet = bankFront.getFtpSet("bat");
                        String localDownloadFilePath = createTempFileDirectory() + File.separator + tmpDownloadFileName;
                        boolean result = doTwice(ftpSet, tmpDownloadFileName, localDownloadFilePath);
                        if (!result) {
                            if (getBankConfig().getValueAsBool("uploadFTPSwifch")) {
                                FtpSet ftpSet2 = bankFront.getFtpSet("bat2");
                                if (ftpSet2 != null) {
                                    result = doTwice(ftpSet2, tmpDownloadFileName, localDownloadFilePath);
                                    if (!result) {
                                        retAts.respCode = "-1";
                                        retAts.respInfo = "第二台FTP批次结果文件下载失败";
                                        retAts.writeAfterDetail();
                                        return retAts;
                                    }
                                }
                            }
                            if (!result) {
                                retAts.respCode = "-1";
                                retAts.respInfo = "第一台FTP批次结果文件下载失败";
                                retAts.writeAfterDetail();
                                return retAts;
                            }
                        }
                        retAts.respCode = "0";
                        retAts.reqSeqID = p_req9198.reqBatchNO;
                        String tmpStrRet = FileHelper.readFileText(localDownloadFilePath, getCharset());
                        WriteBankLogLn2("银行返回文件内容:\r\n" + tmpStrRet);
                        if (StringHelper.hasAnyChar(tmpStrRet)) {
                            StringReader strReader = new StringReader(tmpStrRet);
                            BufferedReader tmpReader = new BufferedReader(strReader);
                            while (true) {
                                String eachline = tmpReader.readLine();
                                if (eachline == null) {
                                    break;
                                }
                                if (eachline.indexOf('|') >= 0) {
                                    RetAtsBatPayRecDetail tmpRetDetail = new RetAtsBatPayRecDetail();
                                    String strjoin = "$$";
                                    eachline = eachline + strjoin;
                                    String[] detailNodes = eachline.split("\\|");
                                    if (detailNodes.length > 4 && existSeqList.containsKey(detailNodes[0])) {
                                        tmpRetDetail.bkSeq = detailNodes[0];
                                        tmpRetDetail.payAmount = detailNodes[3];
                                        tmpRetDetail.payName = detailNodes[1];
                                        tmpRetDetail.payAct = detailNodes[2];
                                        tmpRetDetail.postScript = existSeqList.get(detailNodes[0]);
                                        String tmpRespCode = detailNodes[4];
                                        tmpRetDetail.result = tmpRespCode;
                                        tmpRetDetail.payInfoCode = tmpRespCode;
                                        if (detailNodes.length > 5) {
                                            if (detailNodes[5].contains("未知")) {
                                                tmpRetDetail.memo = detailNodes[4] + StringHelper.trimEnd(detailNodes[5], strjoin);
                                            } else {
                                                tmpRetDetail.memo = StringHelper.trimEnd(detailNodes[5], strjoin);
                                            }
                                        }
                                        retAts.writeRetDetail(tmpRetDetail);
                                    } else if (detailNodes.length <= 4) {
                                        WriteBankLogLn("中信回盘文件内容不符合预期：" + eachline);
                                    } else {
                                        WriteBankLogLn("本地映射文件找不到这笔：" + eachline);
                                    }
                                } else if (eachline.trim().length() > 0) {
                                    WriteBankLogLn("该行内容无效：" + eachline);
                                }
                            }
                        } else {
                            retAts.respCode = "-1";
                            retAts.respInfo = "批次结果文件内容为空!";
                        }
                    } else {
                        retAts.respCode = "-1";
                        retAts.respInfo = "本地批次流水映射文件不存在!";
                    }
                } else {
                    retAts.respCode = "-1";
                    retAts.respInfo = "本地批次流水映射目录不存在，未发生过批次交易!";
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            retAts.respCode = "-1";
            retAts.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }
        retAts.writeAfterDetail();
        return retAts;
    }

    private boolean doTwice(FtpSet ftpSet, String tmpDownloadFileName, String localDownloadFilePath) throws java.io.IOException {
        MixFtp mixFtp2 = new MixFtp(ftpSet);
        FtpReceiver ftpReceiver = mixFtp2.downloadFileFromDir(ftpSet.downDir,tmpDownloadFileName,localDownloadFilePath);
        WriteBankLogLn("批次结果文件下载结果" + ftpReceiver.connMsg);
        return ftpReceiver.isCompleted;
    }
}